package com.breaktian.network.http;

import android.content.Context;
import android.os.SystemClock;
import android.text.TextUtils;


import com.breaktian.network.util.NetworkUtils;

import java.io.IOException;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;


public class NetworkStatsInterceptor implements Interceptor {

    private static final int RETRY_COUNT = 1;

    public static final String TMPL = "{\"net\":\"%1$s\",\"sys\":\"android\",\"url\":\"%2$s\",\"time\":\"%3$s\"," +
            "\"load\":\"%4$s\",\"beginTime\":\"%5$s\",\"endTime\":\"%6$s\",\"error\":\"%7$s\",\"repeat\":\"%8$s\"}";
    private Context mContext;

    public NetworkStatsInterceptor(Context context) {
        this.mContext = context;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        long startTime = SystemClock.uptimeMillis();
        final String beginTime = String.valueOf(System.currentTimeMillis());

        HttpUrl httpUrl = request.url();
        String url = new StringBuffer().append(httpUrl.scheme()).append("://").append(httpUrl.host()).append(httpUrl.encodedPath()).toString();

        int retry = 0;
        IOException exception;
        while (true) {
            try {
                Response response = chain.proceed(request);
                long time = SystemClock.uptimeMillis() - startTime;
                String error = "";
                String status = "success";
                if (!response.isSuccessful()) {
                    error = "response " + response.code();
                }
                stats(url, time, status, beginTime, String.valueOf(System.currentTimeMillis()), error, String.valueOf(retry));
                return response;
            } catch (IOException e) {
                exception = e;
                final String msg = e.getMessage();
                if (TextUtils.isEmpty(msg) || !msg.contains("unexpected end of stream") || ++retry > RETRY_COUNT) {
                    break;
                }
            } catch (RuntimeException e) {
                exception = new IOException("OKHTTP3 RuntimeException \"" + e.getMessage() + "\"" + "is wrapped IOException throw");
                break;
            }
        }
        final String error = exception.getMessage();
        if (!TextUtils.isEmpty(error) && !error.contains("Canceled")) {
            long time = SystemClock.uptimeMillis() - startTime;
            stats(url, time, "fail", beginTime, String.valueOf(System.currentTimeMillis()), exception.getMessage(), String.valueOf(retry));
        }
        throw exception;
    }

    private void stats(String url, long time, String status, String beginTime, String endTime, String error, String retry) {
        String net = NetworkUtils.getNet(mContext);
        String stats = String.format(TMPL, net, url, String.valueOf(time), status, beginTime, endTime, error, retry);
    }
}